package com.example.hotelmanager.common;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.widget.ImageView;

import com.example.hotelmanager.AppException;
import com.example.hotelmanager.net.HttpClientApi;

/**
 * Bitmap管理类
 * 功能包括：1、异步线程加载图片 2、内存图片缓存 3、SD卡图片缓存
 * 使用步骤如下：
 * BitmapManager bmpManager = null; 
 * bmpManager = new BitmapManager(BitmapFactory.decodeResource(context.getResources(),R.drawable.loading)); 
 * bmpManager.loadBitmap(imageURL, imageView);
 * @author zhang_jin1
 */
public class BitmapManager {
	
	private static final int THREAD_POLL_COUNTS = 5;//固定线程池线程个数，暂定为5个
	private static HashMap<String, SoftReference<Bitmap>> cache;
	private static ExecutorService pool;
	private static Map<ImageView, String> imageViews;
	private Bitmap defaultBmp;

	static {
		cache = new HashMap<String, SoftReference<Bitmap>>();
		pool = Executors.newFixedThreadPool(THREAD_POLL_COUNTS); // 固定线程池，
		imageViews = Collections.synchronizedMap(new WeakHashMap<ImageView, String>());
	}

	public BitmapManager() {
	}

	public BitmapManager(Bitmap def) {
		this.defaultBmp = def;
	}

	/**
	 * 设置默认图片
	 * 
	 * @param bmp
	 */
	public void setDefaultBmp(Bitmap bmp) {
		defaultBmp = bmp;
	}

	/**
	 * 加载图片
	 * 
	 * @param url
	 * @param imageView
	 */
	public void loadBitmap(String url, ImageView imageView) {
		loadBitmap(url, imageView, this.defaultBmp, 0, 0);
	}

	/**
	 * 加载图片-可设置加载失败后显示的默认图片
	 * 
	 * @param url
	 * @param imageView
	 * @param defaultBmp
	 */
	public void loadBitmap(String url, ImageView imageView, Bitmap defaultBmp) {
		loadBitmap(url, imageView, defaultBmp, 0, 0);
	}

	/**
	 * 加载图片-可指定显示图片的高宽
	 * 
	 * @param url
	 * @param imageView
	 * @param width
	 * @param height
	 */
	public void loadBitmap(String url, ImageView imageView, Bitmap defaultBmp,int width, int height) {
		imageViews.put(imageView, url);
		Bitmap bitmap = getBitmapFromCache(url);

		if (bitmap != null) {
			// 显示缓存图片
			imageView.setImageBitmap(bitmap);
		} else {
			// 加载SD卡中的图片缓存
			String filename = FileUtils.getFileNameByUrl(url);
			String filepath = imageView.getContext().getFilesDir()+ File.separator + filename;
			File file = new File(filepath);
			if (file.exists()) {
				//显示在 "/data/data/应用名称/files"目录下的图片缓存
				Bitmap bmp = ImageUtils.getBitmap(imageView.getContext(),filename);
				imageView.setImageBitmap(bmp);
			} else {
				
				imageView.setImageBitmap(defaultBmp);//设置默认图片
				queueJob(url, imageView, width, height);//使用线程加载网络图片
			}
		}
	}

	/**
	 * 从缓存中获取图片
	 * @param url
	 */
	private Bitmap getBitmapFromCache(String url) {
		Bitmap bitmap = null;
		if (cache.containsKey(url)) {
			bitmap = cache.get(url).get();
		}
		return bitmap;
	}

	/**
	 * 从网络中加载图片
	 * @param url
	 * @param imageView
	 * @param width
	 * @param height
	 */
	private void queueJob(final String url, final ImageView imageView,final int width, final int height) {
		
		final Handler handler = new Handler() {
			@Override
			public void handleMessage(Message msg) {
				String tag = imageViews.get(imageView);
				if (tag != null && tag.equals(url)) {
					if (msg.obj != null) {
						imageView.setImageBitmap((Bitmap) msg.obj);
						try {
							// 向SD卡中写入图片缓存
							ImageUtils.saveImage(imageView.getContext(),FileUtils.getFileNameByUrl(url),(Bitmap) msg.obj);
						} catch (IOException e) {
							Logger.e(e.getMessage());
						}
					}
				}
			}
		};

		pool.execute(new Runnable() {
			public void run() {
				Message message = Message.obtain();
				message.obj = getNetBitmapAndInitCache(url, width, height);
				handler.sendMessage(message);
			}
		});
	}

	/**
	 * 获取指定大小的网络图片并放入map cache 中
	 * @param url
	 * @param width
	 * @param height
	 */
	private Bitmap getNetBitmapAndInitCache(String url, int width, int height) {
		Bitmap bitmap = null;
		try {
			// http加载图片
			bitmap = downloadNetBitmap(url);
			if (width > 0 && height > 0) {
				// 指定显示图片的高宽
				bitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);
			}
			// 放入缓存
			cache.put(url, new SoftReference<Bitmap>(bitmap));
		} catch (AppException e) {
			e.printStackTrace();
		}
		return bitmap;
	}

	/**
	 * 根据URL下载网络图片
	 * @param url
	 * @return
	 */
	private Bitmap downloadNetBitmap(String url) throws AppException {
		// System.out.println("image_url==> "+url);
		HttpClient httpClient = null;
		GetMethod httpGet = null;
		Bitmap bitmap = null;
		int time = 0;
		do {
			try {
				httpClient = HttpClientApi.getHttpClient();
				httpGet = HttpClientApi.getHttpGet(url, null, null);
				int statusCode = httpClient.executeMethod(httpGet);
				if (statusCode != HttpStatus.SC_OK) {
					throw AppException.http(statusCode);
				}
				InputStream inStream = httpGet.getResponseBodyAsStream();
				bitmap = BitmapFactory.decodeStream(inStream);
				inStream.close();
				break;
			} catch (HttpException e) {
				time++;
				if (time < HttpClientApi.RETRY_TIME) {
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e1) {
					}
					continue;
				}
				// 发生致命的异常，可能是协议不对或者返回的内容有问题
				e.printStackTrace();
				throw AppException.http(e);
			} catch (IOException e) {
				time++;
				if (time < HttpClientApi.RETRY_TIME) {
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e1) {
					}
					continue;
				}
				// 发生网络异常
				e.printStackTrace();
				throw AppException.network(e);
			} finally {
				// 释放连接
				httpGet.releaseConnection();
				httpClient = null;
			}
		} while (time < HttpClientApi.RETRY_TIME);
		return bitmap;
	}

}